package com.ehais.util;

import android.util.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.math.BigInteger;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class ClientManager {
    private static final String TAG="WifiUtil";
    private static ServerThread serverThread = null;
    private static int sum = 0;
    private static Map<String, Socket> clientMap = new HashMap<>();
    private static List<String> clientList = new ArrayList<>();

    private static class ServerThread implements Runnable {

        private ServerSocket server;
        private int port = 5000;
        private boolean isExit = false;// 一个boolean类型的判断 默认是退出状态false

        private OnRequestBack requestBack;

        private String type ;//检测类型  Plumbic 铅酸  Phosphoric 磷酸铁锂

        // 构造方法初始化
        public ServerThread(OnRequestBack _requestBack,String _type) {
            try {
                server = new ServerSocket(port);

                requestBack = _requestBack;
                type = _type;

                Log.i(TAG,"启动server，端口号：" + port +"  , type:"+type);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        /**
         * 1.获得远程服务器的IP 地址.
         * InetAddress inetAddress = socket.getInetAddress();
         * 2.获得远程服务器的端口.
         * int port = socket.getPort();
         * 3. 获得客户本地的IP 地址.
         * InetAddress localAddress = socket.getLocalAddress();
         * 4.获得客户本地的端口.
         * int localPort = socket.getLocalPort();
         * 5.获取本地的地址和端口号
         * SocketAddress localSocketAddress = socket.getLocalSocketAddress();
         * 6.获得远程的地址和端口号
         * SocketAddress remoteSocketAddress = socket.getRemoteSocketAddress();
         */
        @Override
        public void run() {
            try {
                while (!isExit) {
                    // 等待连接
                    Log.i(TAG,"等待手机的连接中... ...");
                    final Socket socket = server.accept();
                    Log.i(TAG,"获取的手机IP地址及端口号：" + socket.getRemoteSocketAddress().toString());
                    /**
                     * 因为考虑到多手机连接的情况 所以加入线程锁 只允许单线程工作
                     */
                    new Thread(new Runnable() {

                        private String text;

                        @Override
                        public void run() {
                            try {
                                synchronized (this) {
                                    // 在这里考虑到线程总数的计算 也代表着连接手机的数量
                                    ++sum;
                                    // 存入到集合和Map中为群发和单独发送做准备
                                    String string = socket.getRemoteSocketAddress().toString();
                                    clientList.add(string);
                                    clientMap.put(string, socket);
                                }


                                synchronized (this) {
                                    // 定义输入输出流
                                    InputStream is = socket.getInputStream();

//                                    private String type ;//检测类型  Plumbic 铅酸  Phosphoric 磷酸铁锂
Log.i(TAG,"捕捉到的:"+type);
                                    if(type.equals("Plumbic")){//Plumbic
                                        byte[] buffer = new byte[2048];
                                        int len;
                                        while ((len = is.read(buffer)) != -1) {
                                            byte[] buffer2 = new byte[len];
                                            System.arraycopy(buffer, 0, buffer2, 0, len);
                                            text = toHexAscii(buffer2);
                                            Log.i(TAG,"铅酸收到的数据为  ：" + text);
                                            requestBack.onSuccessPlumbic(text);
                                        }
                                    } else if(type.equals("Phosphoric")){//Phosphoric 磷酸铁锂
//                                        BufferedReader br = new BufferedReader(new InputStreamReader(is));
//                                        while ((text = br.readLine()) != null) {
//                                            Log.i(TAG,"磷酸铁锂收到的数据为  ：" + text);
//                                            requestBack.onSuccessPhosphoric(text);
//                                        }


/*

                                        byte[] buffer = new byte[2048];
                                        int len;
                                        while ((len = is.read(buffer)) != -1) {
//                                            byte[] buffer2 = new byte[len];
//                                            System.arraycopy(buffer, 0, buffer2, 0, len);
//                                            text = toHexAscii(buffer2);
//                                            Log.i(TAG,"磷酸铁锂收到的数据为  ：" + text);
//                                            requestBack.onSuccessPhosphoric(text);

                                            text = new String(buffer ,0,len);
                                            Log.i(TAG,"磷酸铁锂收到的数据为  ：" + text);
                                            requestBack.onSuccessPhosphoric(text);
                                        }
*/

                                        Scanner reqScan = new Scanner(is);
//                                        if (!reqScan.hasNext()){
//                                            System.out.printf("[%s:%d] 客户端下线!\n",
//                                                    socket.getInetAddress().toString(),
//                                                    socket.getPort());
//
//                                        }
                                        text = reqScan.next();
                                        Log.i(TAG,"磷酸铁锂收到的数据为  ：" + text);
                                        requestBack.onSuccessPhosphoric(text);

                                    }



//                                    byte[] buffer = new byte[1024];
//                                    int len;
//                                    while ((len = is.read(buffer)) != -1) {
//                                        String dx = new String(buffer ,0,len);
//
//
////                                        byte[] buffer2 = new byte[len];
////                                        System.arraycopy(buffer, 0, buffer2, 0, len);
//
////                                        String dx = new String(buffer2 ,"ascii");
//                                        Log.i(TAG,"收到的数据dx ：" + dx);
////                                        text = toHexAscii(buffer2);
////                                        Log.i(TAG,"收到的数据1为 ：" + text);
////                                        requestBack.onSuccess(text);
//
////                                        text16 = bytesToHex(buffer);
////                                        text16 = AsciiToHex.hexByteToString(buffer2);
////
////
////                                        text = new String(buffer2, 0, len);
//
////                                        Log.i(TAG,"收到数据长度  ：" + len);
////                                        Log.i(TAG,"收到的数据为  ：" + text);
////                                        Log.i(TAG,"收到的数据为16：" + text16.length() + "   " + text16);
////                                        Log.i(TAG,"收到的数据为162：" + dx);
////                                        Log.i(TAG,"收到的数据：" + AsciiToHex.printHexString(buffer2));
//
//
//
//                                    }

//                                    char[] data = new char[10];
//                                    BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//                                    int len = 0;
//                                    //3、接收数据
//                                    //处理传输数据大于接收块的容量
//                                    //读取的字符数，如果已到达流的末尾则为-1
//                                    while ((len = br.read(data)) != -1){
//                                        Log.i(TAG,len+"原始字符串"+String.valueOf(data, 0, len));
//
//                                    }
                                }


                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }).start();

                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // 关闭server
        public void stop() {
            isExit = true;
            if (server != null) {
                try {
                    server.close();
                    Log.i(TAG,"已关闭server");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    // 启动server
    public static ServerThread startServer(OnRequestBack _requestBack,String type) {
        Log.i(TAG,"开启server");
        if (serverThread != null) {
            Log.i(TAG,"server不为null正在重启server");
            // 以下为关闭server和socket
            shutDown();
        }
        // 初始化
        serverThread = new ServerThread(_requestBack,type);
        new Thread(serverThread).start();
        Log.i(TAG,"开启server成功");
        return serverThread;
    }


    // 发送消息的方法
//    public static boolean sendMessage(String name, String mag) {
//        try {
//            Socket socket = clientMap.get(name);
//            OutputStream outputStream = socket.getOutputStream();
//            outputStream.write(bytesToHex(mag.getBytes("utf-8")).getBytes());
//            return true;
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        return false;
//    }

    // 群发的方法
    public static boolean sendMsgAll(String msg,String type){
        try {
            msg = msg.replaceAll(" " ,"").replaceAll("\r" ,"").replaceAll("\n" ,"");

//            Log.i(TAG,"type:"+type +" clientMap "+clientMap.size());


            for (Socket socket : clientMap.values()) {
                OutputStream outputStream = socket.getOutputStream();

                if(type.equals("Plumbic")){//Plumbic
                    outputStream.write(AsciiToHex.hexStringToByte(msg));//正式有用的 "00 00 00 00 00 06 01 04 03 E8 00 0A"
                } else if(type.equals("Phosphoric")) {//Phosphoric 磷酸铁锂
                    outputStream.write(msg.getBytes());
                }
                Log.i(TAG,"发送指令:"+msg+" 到 "+socket.getRemoteSocketAddress().toString() + "   类型为："+type);

            }
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

    // 获取线程总数的方法，也等同于<获取已连接了多少台手机>的方法+
    public static int sumTotal() {
        return sum;
    }

    // 一个获取list集合的方法，取到所有连接server的手机的ip和端口号的集合
    public static List<String> getTotalClients() {
        return clientList;
    }

    public static void shutDown() {
        for (Socket socket : clientMap.values()) {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (serverThread != null) serverThread.stop();
        clientMap.clear();
        clientList.clear();
    }





    /**
     * byte数组转十六位字符串（不带空格）
     * @param bytes 待转换的byte数组
     */
    public static String toHexAscii(byte[] bytes) {
        int len = bytes.length;
        StringWriter sw = new StringWriter(len * 2);
        for (int i = 0; i < len; ++i)
            addHexAscii(bytes[i], sw);
        return sw.toString();
    }
    /**
     * byte转16位并拼接
     * @param b     数组
     * @param sw    字符串
     */
    static void addHexAscii(byte b, StringWriter sw) {
        int ub = unsignedPromote(b);
        int h1 = ub / 16;
        int h2 = ub % 16;
        sw.write(toHexDigit(h1));
        sw.write(toHexDigit(h2));
    }

    /**
     * byte取补位数据
     * @param b 数组
     * @return
     */
    public static int unsignedPromote(byte b) {
        return b & 0xff;
    }

    /* note: we do no arg. checking, because     */
    /* we only ever call this from addHexAscii() */
    /* above, and we are sure the args are okay  */
    private static char toHexDigit(int h) {
        char out;
        if (h <= 9) out = (char) (h + 0x30);
        else out = (char) (h + 0x37);
        //System.err.println(h + ": " + out);
        return out;
    }


}
